package com.douyu.data.elasticsearch.service;

import com.alibaba.fastjson.JSON;
import com.douyu.data.up.entity.Up;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.search.MatchQuery;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

@Service
public class ElasticOperator {
    // 低级客户端
    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private RestHighLevelClient elasticClient;

    public void addIndex(String indexName) throws IOException {
        // 1. 创建索引请求
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
        // 客户端执行请求 IndicesClient, 请求后获得响应
        CreateIndexResponse createIndexResponse = elasticClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }

    public void existIndex(String indexName) throws IOException {
        GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
        boolean exists = elasticClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    public void deleteIndex(String indexName) throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
        AcknowledgedResponse delete = elasticClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        System.out.println(delete.isAcknowledged());
    }

    public void addDocument(Up up, String indexName) throws IOException {
        IndexRequest indexRequest = new IndexRequest(indexName);
        indexRequest.id("1");
        indexRequest.timeout(TimeValue.timeValueSeconds(1));
        indexRequest.timeout("1s");

        // 将我吗的数据放入请求，必须是json
        indexRequest.source(JSON.toJSONString(up), XContentType.JSON);
        // 客户端发送请求， 获取响应结果
        IndexResponse index = elasticClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(index.getResult());
        System.out.println(index.status());
    }

    public void getDocument(String id, String indexName) throws IOException {
        GetRequest getRequest = new GetRequest(indexName, id);
//        getRequest.fetchSourceContext(new FetchSourceContext(false));
//        getRequest.storedFields("_none_");

        boolean exists = elasticClient.exists(getRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
        if(exists){
            GetResponse documentFields = elasticClient.get(getRequest, RequestOptions.DEFAULT);
            System.out.println(documentFields.getSourceAsString());
        }
    }

    // 实现的是部分更新
    public void updateDocument(String indexName, String id,Up up) throws IOException {
        UpdateRequest updateRequest = new UpdateRequest(indexName, id);
        updateRequest.timeout("1s");

        updateRequest.doc(JSON.toJSONString(up), XContentType.JSON);
        UpdateResponse update = elasticClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(update.getResult());
    }

    public void deleteDocument(String id, String indexName) throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest(indexName, id);
        deleteRequest.timeout("1s");

        DeleteResponse delete = elasticClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(delete.getResult());
    }

    // 批处理
    public void bulkDocument(String indexName, List<Up> upList) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        for (Up up : upList) {
            // 对于所有的操作都可以批量
            bulkRequest.add(new IndexRequest(indexName)
                    .id(up.getId()) // 如果不指定，就使用随机生成的
                    .source(JSON.toJSONString(up), XContentType.JSON));
        }
        BulkResponse bulk = elasticClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulk.getItems());
    }

    public void searchDocument(String indexName) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        // 构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder must = QueryBuilders.boolQuery()
                .must(QueryBuilders.termsQuery("association.keyword", "煋禾互娱", "小奶团"))
                .must(QueryBuilders.rangeQuery("level").gt(20).lt(90));
//        searchSourceBuilder.from(1);
//        searchSourceBuilder.size(1);
        searchSourceBuilder.fetchSource(new String[]{"name", "association", "attention"}, null);
        searchSourceBuilder.query(must);
        searchSourceBuilder.highlighter();
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = elasticClient.search(searchRequest, RequestOptions.DEFAULT);
        for (SearchHit hit : search.getHits().getHits()) {
            System.out.println(hit.getSourceAsString());
        }
    }
}
